#pragma once

#include <mcp/config.h>
#include <mcp/client/client.h>

#include <memory>
#include <string>
#include <vector>
#include <optional>
#include <functional>

namespace mcp {
namespace client {

/// @brief Simple client with synchronous interface
class SimpleClient {
public:
    explicit SimpleClient(const std::string& transport_url,
                         const ClientConfig& config = {});
    ~SimpleClient();

    /// @brief Connect to server
    /// @return true if connected successfully, false otherwise
    bool connect();

    /// @brief Disconnect from server
    void disconnect();

    /// @brief Check if connected to server
    /// @return true if connected, false otherwise
    bool is_connected() const;

    /// @brief Get server information
    /// @return Server information or error
    std::expected<json::Value, std::string> get_server_info();

    /// @brief List available tools
    /// @return List of tools or error
    std::expected<std::vector<types::Tool>, std::string> list_tools();

    /// @brief Call a tool synchronously
    /// @param name Tool name
    /// @param arguments Tool arguments
    /// @return Tool result or error
    std::expected<json::Value, std::string> call_tool(const std::string& name,
                                                       const json::Value& arguments);

    /// @brief List available resources
    /// @return List of resources or error
    std::expected<std::vector<types::Resource>, std::string> list_resources();

    /// @brief Read a resource synchronously
    /// @param uri Resource URI
    /// @return Resource content or error
    std::expected<types::ResourceContent, std::string> read_resource(const std::string& uri);

    /// @brief List available prompts
    /// @return List of prompts or error
    std::expected<std::vector<types::Prompt>, std::string> list_prompts();

    /// @brief Call a prompt synchronously
    /// @param name Prompt name
    /// @param arguments Prompt arguments
    /// @return Prompt messages or error
    std::expected<std::vector<types::PromptMessage>, std::string> call_prompt(
        const std::string& name,
        const json::Value& arguments);

    /// @brief Send a logging message
    /// @param level Log level
    /// @param message Log message
    /// @return true if sent successfully, false otherwise
    bool send_log(types::LogLevel level, const std::string& message);

    /// @brief Set notification handler
    /// @param handler Function to handle notifications
    void set_notification_handler(std::function<void(const std::string&, const json::Value&)> handler);

    /// @brief Set error handler
    /// @param handler Function to handle errors
    void set_error_handler(std::function<void(const std::string&)> handler);

private:
    struct Impl;
    std::unique_ptr<Impl> impl_;
};

/// @brief Convenience function to create simple client
std::unique_ptr<SimpleClient> create_simple_client(const std::string& transport_url,
                                                   const ClientConfig& config = {});

} // namespace client
} // namespace mcp